<?php
/**
 * Created by PhpStorm.
 * User: youqingsong
 * redis操作工具类
 * Date: 2021/4/6
 * Time: 16:28
 */

namespace Ktnw\RedisSupport\Utils;

use Illuminate\Redis\Connections\Connection;
use Illuminate\Support\Facades\Redis;

class RedisUtils
{
    // 创建静态私有的变量保存该类对象
    static private $redis;

    // 防止使用clone克隆对象
    private function __clone()
    {
    }

    /**
     * 根据key获取redis实例
     * key为 config/database.php中redis配置的key
     * @return Connection
     */
    private static function initRedis(): Connection
    {
        //判断$instance是否是Singleton的对象，不是则创建
        if (!self::$redis instanceof Redis) {
            $key         = self::getUseRedisKey();
            self::$redis = Redis::connection($key);
        }
        return self::$redis;
    }

    /**
     * 根据key获取redis实例
     * @param string $key
     * @return Connection
     */
    public static function getInstance(string $key = ''): Connection
    {
        if (empty($key)) {
            $key = self::getUseRedisKey();
        }
        return Redis::connection($key);
    }

    /**
     * 保存有序集合
     * @param $key
     * @param array $membersAndScoresDictionary eg:["member1"=>"scores1", "member2"=>"scores2"]
     * member: 成员
     * scores: 只能为int或float
     * @return bool
     */
    public static function zadd($key, array $membersAndScoresDictionary)
    {
        return self::initRedis()->zadd($key, $membersAndScoresDictionary) > 0;
    }

    /**
     * 按score升序排列
     * @param string $key
     * @param $start int 开始索引 0
     * @param $stop int 截止索引（包含） 0，表示第一个元素，-1 表示最后一个元素，-2 表示倒数第二个元素
     * @param bool $withscores 是否返回score
     * @return array
     */
    public static function zrange(string $key, int $start, int $stop, bool $withscores = false)
    {
        return self::initRedis()->zrange($key, $start, $stop, ['withscores' => $withscores]);
    }

    /**
     * 按score降序排列
     * @param string $key
     * @param $start int 开始索引 0
     * @param $stop int 截止索引（包含） 0，表示第一个元素，-1 表示最后一个元素，-2 表示倒数第二个元素
     * @param bool $withscores 是否返回score
     * @return array
     */
    public static function zrevrange(string $key, int $start, int $stop, bool $withscores = false)
    {
        return self::initRedis()->zrevrange($key, $start, $stop, ['withscores' => $withscores]);
    }

    /**
     * 根据成员查询score
     * @param $key
     * @param $member
     * @return string|null
     */
    public static function zscore($key, $member)
    {
        return self::initRedis()->zscore($key, $member);
    }

    /**
     * 根据score从低到高，返回member的index
     * @param $key
     * @param $member
     * @return int|null
     */
    public static function zrank($key, $member)
    {
        return self::initRedis()->zrank($key, $member);
    }

    /**
     * 根据score从高到低排序，返回member在有序集key中的index
     * @param $key
     * @param $member
     * @return int|null
     */
    public static function zrevrank($key, $member)
    {
        return self::initRedis()->zrevrank($key, $member);
    }

    /**
     * 保存到redis中
     * @param $key
     * @param $val string|array
     * @return mixed
     */
    public static function set($key, $val)
    {
        if (is_array($val)) {
            $val = json_encode($val, JSON_UNESCAPED_UNICODE);
        }
        return self::initRedis()->set($key, $val);
    }


    /**
     * 增加一个元素,但不能重复
     * 若重复，返回false
     * @param $key
     * @param $val
     * @return int
     */
    public static function setnx($key, $val)
    {
        return self::initRedis()->setnx($key, $val);
    }

    /**
     * 带存储时效保存
     * @param $key
     * @param $seconds
     * @param $val
     * @return int
     */
    public static function setex($key, $seconds, $val): int
    {
        if (is_array($val)) {
            $val = json_encode($val, JSON_UNESCAPED_UNICODE);
        }
        return self::initRedis()->setex($key, $seconds, $val);
    }

    /**
     * 从redis中获取
     * @param $key
     * @return mixed
     */
    public static function get($key)
    {
        return self::initRedis()->get($key);
    }

    /**
     * @param $method
     * @param array $parameters
     * @return mixed
     */
    public static function command($method, array $parameters = [])
    {
        return self::initRedis()->command($method, $parameters);
    }

    /**
     * 保存多个
     * @param array $dictionary
     * @return mixed
     */
    public static function mset(array $dictionary)
    {
        return self::initRedis()->mset($dictionary);
    }

    /**
     * 取出多个
     * @param array $keys
     * @return array
     */
    public static function mget(array $keys)
    {
        return self::initRedis()->mget($keys);
    }

    /**
     * 校验是否存在key
     * @param $key
     * @return bool
     */
    public static function exists($key)
    {
        return self::initRedis()->exists($key) > 0;
    }

    /**
     * 删除
     * @param $keys string|array
     * @return bool
     */
    public static function del($keys)
    {
        return self::initRedis()->del($keys) > 0;
    }

    /**
     * 重新设计有效期
     * @param $key
     * @param $seconds
     * @return bool
     */
    public static function expire($key, $seconds)
    {
        return self::initRedis()->expire($key, $seconds) > 0;
    }


    private static function getUseRedisKey()
    {
        return config('redisConfig.use_redis_key');
    }

}